package com.ChainBizPro.system.aop;

import com.ChainBizPro.system.annotation.AuthCheck;
import com.ChainBizPro.system.common.ErrorCode;
import com.ChainBizPro.system.exception.BusinessException;
import com.ChainBizPro.system.model.domain.User;
import com.ChainBizPro.system.model.enums.UserRoleEnum;
import com.ChainBizPro.system.service.UserService;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

/**
 * 权限校验 AOP
 * 切面类，拦截所有带有 @AuthCheck 注解的方法 进行权限校验
 *
 * @author liusijia
 */
@Aspect
@Component
public class AuthInterceptor {

    @Resource
    private UserService userService;

    /**
     * 执行拦截
     *
     * @param joinPoint joinPoint
     * @param authCheck authCheck
     * @return Object
     */
    @Around("@annotation(authCheck)")
    public Object doInterceptor(ProceedingJoinPoint joinPoint, AuthCheck authCheck) throws Throwable {
        // 获取当前登录用户
        RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();
        HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
        User loginUser = userService.getLoginUser(request);

        if (loginUser == null) {
            throw new BusinessException(ErrorCode.NOT_LOGIN_ERROR);
        }

        String userRole = loginUser.getUserRole();

        // 必须有某个角色
        String mustRole = authCheck.mustRole();
        if (StringUtils.isNotBlank(mustRole)) {
            UserRoleEnum requiredRole = UserRoleEnum.getEnumByValue(mustRole);
            if (requiredRole == null) {
                throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "角色不存在");
            }
            if (!mustRole.equals(userRole)) {
                throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "无访问权限");
            }
        }

        // 必须有某些角色中的任意一个
        String[] anyRole = authCheck.anyRole();
        if (anyRole.length > 0) {
            boolean hasAnyRole = false;
            for (String role : anyRole) {
                if (role.equals(userRole)) {
                    hasAnyRole = true;
                    break;
                }
            }
            if (!hasAnyRole) {
                throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "无访问权限");
            }
        }

        // 必须有全部角色
        String[] hasRoles = authCheck.hasRoles();
        if (hasRoles.length > 0) {
            for (String role : hasRoles) {
                if (!role.equals(userRole)) {
                    throw new BusinessException(ErrorCode.NO_AUTH_ERROR, "无访问权限");
                }
            }
        }

        // 通过权限校验，放行
        return joinPoint.proceed();
    }
}
